﻿using MQTTnet.Client;
using MQTTnet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MQTTnet.Protocol;
using MQTTnet.Extensions.ManagedClient;
using System.Runtime.CompilerServices;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using MyMQTTX.Helper;
using MyMQTTX.Entity;
using Newtonsoft.Json;

namespace MyMQTTX
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        MqttFactory factory;
        IMqttClient mqttClient;
        Boolean sync;
        InfluxDBClient db;

        private void button_connect_Click(object sender, EventArgs e)
        {
            try
            {
                // 创建MQTT客户端工厂
                factory = new MqttFactory();
                // 创建MQTT客户端
                mqttClient = factory.CreateMqttClient();
                // 创建连接选项
                var options = new MqttClientOptionsBuilder()
                .WithTcpServer(this.textBox_server.Text.Trim(), Int16.Parse(this.textBox_port.Text.Trim())) // MQTT代理地址和端口
                    .Build();
                options.Credentials = new MqttClientCredentials(this.textBox_name.Text.Trim(), Encoding.UTF8.GetBytes(this.textBox_pwd.Text.Trim()));
                options.Timeout = TimeSpan.FromSeconds(5000);
                options.WillQualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce;
                if ("AtLeastOnce".Equals(this.comboBox_Qos.Text.Trim()))
                {
                    options.WillQualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce;
                }
                else if ("ExactlyOnce".Equals(this.comboBox_Qos.Text.Trim()))
                {
                    options.WillQualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce;
                }
                options.ClientId = this.textBox_chientID.Text.Trim();
                mqttClient.ConnectAsync(options);
                this.label_state.Text = "连接成功";
                this.label_state.ForeColor = Color.Green;
                this.textBox_log.AppendText(getMsg("MQTT服务连接成功···\r\n"));
                this.button_disconnect.Enabled = true;
                this.button_connect.Enabled = false;

                this.textBox_port.Enabled = false;
                this.textBox_chientID.Enabled = false;
                this.textBox_server.Enabled = false;
                this.textBox_name.Enabled = false;
                this.textBox_pwd.Enabled = false;
                this.comboBox_Qos.Enabled = false;
            }
            catch(Exception ex)
            {
                this.textBox_log.AppendText(ex.Message+ "\r\n");
            }
        }


        private void button_disconnect_Click(object sender, EventArgs e)
        {
            try
            {
                mqttClient.Dispose();
                this.button_connect.Enabled = true;
                this.button_disconnect.Enabled = false;
                this.label_state.Text = "连接断开";
                this.label_state.ForeColor = Color.Red;
                this.textBox_log.AppendText(getMsg("MQTT服务连接断开···\r\n"));

                this.textBox_port.Enabled = true;
                this.textBox_chientID.Enabled = true;
                this.textBox_server.Enabled = true;
                this.textBox_name.Enabled = true;
                this.textBox_pwd.Enabled = true;
                this.comboBox_Qos.Enabled = true;

                this.button_dis_sub.Enabled = false;
                this.button_pub.Enabled = false;
                this.button_sub.Enabled = false;

                this.textBox_sub.Text = "";
                this.textBox_pub.Text = "";
                this.textBox_pubMsg.Text = "";
            }
            catch(Exception ex)
            {
                this.button_connect.Enabled = false;
                this.button_disconnect.Enabled = true;

                this.textBox_port.Enabled = false;
                this.textBox_chientID.Enabled = false;
                this.textBox_server.Enabled = false;
                this.textBox_name.Enabled = false;
                this.textBox_pwd.Enabled = false;
                this.comboBox_Qos.Enabled = false;

                this.textBox_log.AppendText(getMsg("MQTT服务连接断开失败···\r\n"));
            }
        }

        private async void button_pub_Click(object sender, EventArgs e)
        {
            try
            {
                if ("".Equals(this.textBox_pub.Text.Trim()))
                {
                    this.textBox_log.AppendText(getMsg("请先输入发布主题...\r\n"));
                }
                else if("".Equals(this.textBox_pubMsg.Text.Trim()))
                {
                    this.textBox_log.AppendText(getMsg("请先输入发布内容...\r\n"));
                }
                else
                {
                    if ("Hex".Equals(this.comboBox_code_pub.Text.Trim()))
                    {
                        string pubmsg = this.textBox_pubMsg.Text.Trim();
                        String[] decByte = pubmsg.Split(' ');
                        byte[] sendData = new byte[decByte.Length];
                        for (int i = 0; i < decByte.Length; i++)
                        {
                            sendData[i] = Convert.ToByte(decByte[i], 16);
                        }
                        await mqttClient.PublishAsync(new MqttApplicationMessageBuilder()
                                .WithTopic(this.textBox_pub.Text.Trim()) // 主题
                                .WithPayload(sendData)
                                .WithRetainFlag()
                                .Build());
                    }
                    else if("Plaintext".Equals(this.comboBox_code_pub.Text.Trim()))
                    {
                        await mqttClient.PublishAsync(new MqttApplicationMessageBuilder()
                                .WithTopic(this.textBox_pub.Text.Trim()) // 主题
                                .WithPayload(this.textBox_pubMsg.Text.Trim())
                                .WithRetainFlag()
                                .Build());
                    }
                    this.textBox_log.AppendText(getMsg("发布消息：" + this.textBox_pubMsg.Text.Trim()+ "\r\n"));
                }
            }catch(Exception ex)
            {
                this.textBox_log.AppendText(getMsg("发布消息失败，"+ex.Message+"...\r\n"));
            }
        }

        private void button_sub_Click(object sender, EventArgs e)
        {
            try
            {
                // 订阅事件
                mqttClient.SubscribeAsync(this.textBox_sub.Text.Trim());

                mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync1;
                this.textBox_log.AppendText(getMsg("订阅消息成功...\r\n"));
                this.button_dis_sub.Enabled = true;
                this.button_sub.Enabled = false;
            }
            catch(Exception ex)
            {
                this.button_dis_sub.Enabled = false;
                this.button_sub.Enabled = true;
                this.textBox_log.AppendText(getMsg("订阅消息失败，请确保连接正常...\r\n"));
            }
        }

        /// <summary>
        /// 订阅消息
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        private Task MqttClient_ApplicationMessageReceivedAsync1(MqttApplicationMessageReceivedEventArgs arg)
        {
            Invoke(new Action(() =>
            {
                String PayloadMsg = "";
                if ("Hex".Equals(this.comboBox_code_sub.Text.Trim()))
                {
                    PayloadMsg = BitConverter.ToString(arg.ApplicationMessage.Payload).Replace("-", " ");
                }
                else if("Plaintext".Equals(this.comboBox_code_sub.Text.Trim()))
                {
                    PayloadMsg = arg.ApplicationMessage.ConvertPayloadToString();
                }
                this.textBox_sub_msg.AppendText(getMsg("订阅消息：" + PayloadMsg ));
                this.textBox_log.AppendText(getMsg("订阅消息：" + PayloadMsg ));
                if (sync)
                {
                    if (!"".Equals(this.comboBox_measurements.Text.Trim()))
                    {
                        string cmd = string.Format(this.comboBox_measurements.Text.Trim() + ",week="+ PayloadMsg.Replace(" ","-") + " mood=5,record=1");
                        db.Write(this.comboBox_databases.Text.Trim(), cmd);
                    }

                    //指定时间记录
                    /*long _time = (DateTime.Now.AddDays(1).ToUniversalTime().Ticks - 621355968000000000) * 100;
                    string cmd = string.Format("cpu,week=monday mood=5,state=4 {0}", _time);
                    db.Write("test", cmd);*/

                }
            }));
           
            return null;
        }

        public void updateSubMsg(String str)
        {
            this.textBox_sub_msg.AppendText(str+"\r\n");
        }

        private void button_clean_subMsg_Click(object sender, EventArgs e)
        {
            this.textBox_sub_msg.Clear();
        }

        private void button_clean_logMsg_Click(object sender, EventArgs e)
        {
            this.textBox_log.Clear();
        }

        private void button_dis_sub_Click(object sender, EventArgs e)
        {
            try
            {
                mqttClient.UnsubscribeAsync(this.textBox_pub.Text.Trim());

                this.textBox_log.AppendText(getMsg("取消订阅成功...\r\n"));

                this.button_dis_sub.Enabled = false;
                this.button_sub.Enabled=true;
            }
            catch (Exception ex)
            {
                this.button_dis_sub.Enabled = true;
                this.button_sub.Enabled = false;
                this.textBox_log.AppendText(getMsg("取消订阅失败，请确保连接正常...\r\n"));
            }
        }

        public String getMsg(String msg)
        {
            return DateTime.Now.ToString("\r\n[HH:mm:ss]--") + msg;
        }

        private void textBox_sub_TextChanged(object sender, EventArgs e)
        {
            if (!"".Equals(this.textBox_sub.Text.Trim()) && !this.button_connect.Enabled)
            {
                this.button_sub.Enabled = true;
            }
            else
            {
                this.textBox_log.AppendText(getMsg("请先连接MQTT服务器...\r\n"));
            }
        }

        private void textBox_pub_TextChanged(object sender, EventArgs e)
        {
            if (this.button_connect.Enabled)
            {
                this.textBox_log.AppendText(getMsg("请先连接MQTT服务器...\r\n"));
            }
            else
            {
                this.button_pub.Enabled = true;
            }
            /*if (!"".Equals(this.textBox_pub.Text.Trim()) && !this.button_connect.Enabled)
            {
                if ("".Equals(this.textBox_pubMsg.Text.Trim()))
                {
                    this.textBox_log.AppendText(getMsg("还需输入内容便可发布...\r\n"));
                }
                else
                {
                    this.button_pub.Enabled = true;
                }
            }
            else
            {
                this.textBox_log.AppendText(getMsg("请先连接MQTT服务器...\r\n"));
            }*/
        }

        private void textBox_pubMsg_TextChanged(object sender, EventArgs e)
        {
            if (this.button_connect.Enabled)
            {
                this.textBox_log.AppendText(getMsg("请先连接MQTT服务器...\r\n"));
            }
            else
            {
                this.button_pub.Enabled = true;
            }
           /* if (!"".Equals(this.textBox_pubMsg.Text.Trim()) && !this.button_connect.Enabled)
            {
                if ("".Equals(this.textBox_pub.Text.Trim()))
                {
                    this.textBox_log.AppendText(getMsg("还需输入主题便可发布...\r\n"));
                }
                else
                {
                    this.button_pub.Enabled = true;
                }
            }
            else
            {
                this.textBox_log.AppendText(getMsg("请先连接MQTT服务器...\r\n"));
            }*/
        }

        private void button_connect_DB_Click(object sender, EventArgs e)
        {
            try
            {
                if ("连接".Equals(this.button_connect_DB.Text.Trim())){
                db= new InfluxDBClient(this.textBox_DB_host.Text.Trim(), this.textBox_DB_name.Text.Trim(), this.textBox_DB_pwd.Text.Trim());
                string sql = string.Format("show databases");
                string result = db.Query("test", sql); //数据库名，查询语句
                Root rt = JsonConvert.DeserializeObject<Root>(result);
                
                List<List<String>> databases =rt.results[0].series[0].values.ToList();
                for(int i=0;i< databases.Count(); i++)
                {
                    this.comboBox_databases.Items.Add(databases[i][0]);
                    Console.WriteLine(databases[i][0]);
                }
                this.button_sync_sub.Enabled = true;
                this.button_connect_DB.Text = "断开连接";
                this.textBox_log.AppendText(getMsg("influxDB连接成功...\r\n"));

                }
                else
                {
                    db = null;
                    this.button_sync_sub.Enabled = false;
                    this.button_connect_DB.Text = "连接";
                }
            }
            catch(Exception ex)
            {
                this.button_connect_DB.Text = "连接";
                this.textBox_log.AppendText(getMsg("influxDB连接失败...\r\n"));
            }
        }

        private void button_sync_sub_Click(object sender, EventArgs e)
        {
            if (!this.button_dis_sub.Enabled)
            {
                this.textBox_log.AppendText(getMsg("请先完成消息订阅...\r\n"));
                return;
            }
            if ("".Equals(this.comboBox_databases.Text.Trim()))
            {
                this.textBox_log.AppendText(getMsg("请先选择database...\r\n"));
                return;
            }
            if ("".Equals(this.comboBox_measurements.Text.Trim()))
            {
                this.textBox_log.AppendText(getMsg("请先选择measurements...\r\n若没有可任意输入..."));
                return;
            }
            if ("同步订阅".Equals(this.button_sync_sub.Text.Trim()))
            {
                this.sync = true;
                this.button_sync_sub.Text = "取消同步";
            }
            else if ("取消同步".Equals(this.button_sync_sub.Text.Trim()))
            {
                this.sync = false;
                this.button_sync_sub.Text = "同步订阅";
            }
        }

        private void comboBox_databases_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                db = new InfluxDBClient(this.textBox_DB_host.Text.Trim(), this.textBox_DB_name.Text.Trim(), this.textBox_DB_pwd.Text.Trim());
                string sql = string.Format("show measurements");
                string result = db.Query(this.comboBox_databases.Text.Trim(), sql); //数据库名，查询语句
                Root rt = JsonConvert.DeserializeObject<Root>(result);
                if (rt.results[0].series != null)
                {
                    List<List<String>> measurements = rt.results[0].series[0].values.ToList();
                    this.comboBox_measurements.Items.Clear();
                    for (int i = 0; i < measurements.Count(); i++)
                    {
                        this.comboBox_measurements.Items.Add(measurements[i][0]);
                        Console.WriteLine(measurements[i][0]);
                    }
                    this.comboBox_measurements.Text = "";
                    this.comboBox_measurements.Enabled = true;
                    this.textBox_log.AppendText(getMsg("influxDB查询成功...\r\n"));
                }
                else
                {
                    this.comboBox_measurements.Text = "";
                    this.comboBox_measurements.Items.Clear();
                }
            }
            catch (Exception ex)
            {
                this.textBox_log.AppendText(getMsg("influxDB查询失败...\r\n"));
            }
        }

        private void comboBox_measurements_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.button_sync_sub.Enabled = true;
        }





    }
}
